package com.yao.ro.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yao.common.enums.business.ro.FinishStatusEnum;
import com.yao.common.enums.business.ro.GoodsTypeEnum;
import com.yao.common.exception.BusinessException;
import com.yao.ro.entity.dto.EquipmentDto;
import com.yao.ro.entity.dto.ExchangeDto;
import com.yao.ro.entity.dto.GoodsDto;
import com.yao.ro.entity.qo.GoodsQo;
import com.yao.ro.entity.vo.GoodsVo;
import com.yao.ro.mapper.GoodsMapper;
import com.yao.ro.mapper.sql.GoodsWrapper;
import com.yao.ro.service.EquipmentService;
import com.yao.ro.service.ExchangeService;
import com.yao.ro.service.GoodsService;
import com.yao.ro.util.PriceUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.MathContext;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * 物品表 接口实现
 *
 * @author autoCode
 * @version 1.0.0-SNAPSHOT
 * @date 2020-04-09
 */
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, GoodsDto> implements GoodsService {

    @Autowired
    private GoodsMapper mapper;

    @Autowired
    private ExchangeService exchangeService;

    @Autowired
    private EquipmentService equipmentService;

    @Value("${ro.rate: 0.1}")
    private BigDecimal rate;

    @Value("${ro.fee: 0.01}")
    private BigDecimal fee;

    @Override
    @Transactional(isolation = Isolation.REPEATABLE_READ, rollbackFor = BusinessException.class)
    public void add(GoodsDto dto) {

        // 校验
        this.check(dto);

        /*
         * 1.新增商品信息
         * 2.新增交易所信息
         * 3.如果是装备类型，则增加装备制作
         */
        if (null != dto.getPurchasePrice()) {
            // 计算最低出售价格  （购买价格 / 税率） + （最低出售价格*上架费率）
            BigDecimal salePrice = dto.getPurchasePrice().divide(BigDecimal.ONE.subtract(rate), MathContext.DECIMAL32);

            salePrice = salePrice.add(salePrice.multiply(fee));

            dto.setSalePrice(salePrice);
        }

        if (!this.save(dto)) {
            throw new BusinessException("新增商品信息失败");
        }

        // 新增交易所信息
        ExchangeDto exchangeDto = new ExchangeDto();
        exchangeDto.setGoodsId(dto.getId()).setPrice(dto.getPrice()).setHistoryMinPrice(dto.getPrice())
                .setHistoryMaxPrice(dto.getPrice());
        JSONObject obj = JSONUtil.createObj();
        obj.put("time", LocalDateTime.now());
        obj.put("price", dto.getPrice());
        JSONArray arr = JSONUtil.createArray();
        arr.put(obj);
        exchangeDto.setHistoryPrice(JSONUtil.toJsonStr(arr));

        if (!exchangeService.save(exchangeDto)) {
            throw new BusinessException("新增商品信息失败");
        }

        // 装备类型并且需要制作
        if (GoodsTypeEnum.RQU == dto.getType() && 1 == dto.getGenFlag()) {
            // 新增装备制作
            EquipmentDto equipmentDto = new EquipmentDto();
            equipmentDto.setGoodsId(dto.getId()).setEquipName(dto.getName()).setCost(dto.getCost()).setPrice(dto.getPrice())
                    .setHistoryMaxPrice(exchangeDto.getHistoryMaxPrice()).setHistoryMinPrice(exchangeDto.getHistoryMinPrice()).setFinishStatus(FinishStatusEnum.UNFINISHED.getCode());

            if (!equipmentService.save(equipmentDto)) {
                log.warn("新增制作装备信息失败");
            }
        }
    }

    @Override
    @Transactional(isolation = Isolation.REPEATABLE_READ, rollbackFor = BusinessException.class)
    public void modifyById(GoodsDto model) {

        GoodsDto goods = Optional.ofNullable(this.getById(model.getId()))
                .orElseThrow(() -> new BusinessException("根据id:{[]}找不到商品.", model.getId()));

        if (null != model.getPurchasePrice()) {
            // 计算最低出售价格  （购买价格 / 税率） + （最低出售价格*上架费率）
            BigDecimal salePrice = model.getPurchasePrice().divide(BigDecimal.ONE.subtract(rate), MathContext.DECIMAL32);

            salePrice = salePrice.add(salePrice.multiply(fee));

            model.setSalePrice(salePrice);
        }

        // 当前价格
        BigDecimal price = model.getPrice();

        // 如果更新了价格，则同步更新交易所价格
        if (!price.equals(goods.getPrice())) {
            exchangeService.updatePriceByGoodsId(model.getId(), price);
        }

        this.updateById(model);

    }

    @Override
    public IPage<GoodsVo> page(IPage<GoodsDto> page, GoodsQo qo) {




        IPage<GoodsVo> page1 = mapper.page(page, qo);

        page1.getRecords().forEach(e -> {
            // 价格取4位
            e.setPrice(PriceUtils.formatter(e.getPrice()));
            e.setHistoryMaxPrice(PriceUtils.formatter(e.getHistoryMaxPrice()));
            e.setHistoryMinPrice(PriceUtils.formatter(e.getHistoryMinPrice()));
        });

        return page1;
    }

    @Override
    public List<GoodsDto> listByName(String name) {

        Wrapper<GoodsDto> wrapper = GoodsWrapper.likeName(name);

        return this.list(wrapper);
    }

    @Override
    public List<GoodsDto> listByCondition(GoodsDto condition) {

        Wrapper<GoodsDto> wrapper = GoodsWrapper.byCondition(condition);

        return this.list(wrapper);

    }

    /**
     * 功能描述 : 检查入参
     *
     * @param dto
     * @author yaoyuming
     * @date 2020/5/21 0021
     */
    private void check(GoodsDto dto) {

        // 检查商品名称
        if (StrUtil.isNotEmpty(dto.getName())) {
            Wrapper<GoodsDto> query = GoodsWrapper.byName(dto.getName());

            GoodsDto one = this.getOne(query, false);

            if (ObjectUtil.isNotNull(one)) {
                throw new BusinessException("已存在该商品：{}", dto.getName());
            }

        }

    }


}